package cn.ilikes.tools.nosql.jpa.persistences;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.Table;

import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.JPASQLPersistenUnitEnv;
import cn.ilikes.tools.nosql.jpa.classloads.ClassFilter;
import cn.ilikes.tools.nosql.jpa.classloads.URLPathLoadResources.ResourcesType;
import cn.ilikes.tools.nosql.jpa.configs.JPASQLPersistenceUnitMetadata;
import cn.ilikes.tools.nosql.jpa.metadatas.EntityMetaData;
import cn.ilikes.tools.nosql.jpa.metadatas.processor.TableProcessor;
import cn.ilikes.tools.nosql.jpa.metadatas.processor.TableProcessorException;

public class ClassFilterImpl implements ClassFilter {

	private static Logger logger = Loggerfactory.instance(ClassFilterImpl.class);

	private JPASQLPersistenUnitEnv persistenUnitEnvs;
	private List<String> containClasses;

	public ClassFilterImpl(JPASQLPersistenUnitEnv persistenUnitEnv) {
		this.persistenUnitEnvs = persistenUnitEnv;
		containClasses = containClasses();

	}

	private List<String> containClasses() {
		JPASQLPersistenceUnitMetadata persistenceUnitMetadata = persistenUnitEnvs.getPersistenceUnitMetadata();
		List<String> containClasses = persistenceUnitMetadata.getClasses();
		return containClasses;
	}

	@Override
	public void filter(String resourcesName, byte[] ss) {
		try {

			Class<?> clazz = persistenUnitEnvs.getPersistenUnitClassLoader().loadClass(resourcesName);
			Table table = clazz.getAnnotation(Table.class);
			if (table == null)
				return;
			String persistenUnitName = persistenUnitEnvs.getPersistenUnitName();
			if (table.schema() != null && table.schema().equals(persistenUnitName)) {
				if (clazz.isAnnotationPresent(Entity.class) || clazz.isAnnotationPresent(Table.class)) {
					try {
						EntityMetaData entityMetaData = new EntityMetaData(persistenUnitName, clazz, persistenUnitEnvs);
						TableProcessor tableProcessor = new TableProcessor();
						tableProcessor.process(clazz, entityMetaData);
						//if (Loggerfactory.isdebug(logger))
						Loggerfactory.info(logger, "Entity Meta Data Factory load Entity Meta  class :" + clazz + ";   entityMetaData  " + entityMetaData);
						persistenUnitEnvs.getMetaDataManagerFactory().loadIEntityMetaDatas(clazz, entityMetaData);
					} catch (TableProcessorException e) {
						Loggerfactory.error(logger, "Entity Meta Data Factory not  load Entity Meta success !   class :" + clazz.getName(), e);
					}
				}
			} else {
				if (table.schema() == null) {
					Loggerfactory.warn(logger, "clazz : " + clazz.getSimpleName() + "  @Table schema is null ; please set @Table schema ");
				}
				if (table.schema().equals(persistenUnitName)) {
					Loggerfactory
							.warn(logger, "clazz : " + clazz.getSimpleName() + "  @Table schema  != " + persistenUnitName
									+ " ; please set @Table schema = pu name ");
				}
			}

		} catch (ClassNotFoundException e) {
		}
	}

	@Override
	public boolean isFilter(String resourcesName, ResourcesType resourcesType) {

		if (resourcesType.equals(ResourcesType.classes)) {

			return filtercontainClasses(resourcesName);

		} else
			return false;
	}

	private boolean filtercontainClasses(String resourcesName) {
		for (String containClasse : containClasses) {
			if (containClasse.endsWith(".*")) {
				if (resourcesName.startsWith(containClasse.substring(0, containClasse.length() - 2))) {
					return true;
				}
			} else {
				if (resourcesName.endsWith(containClasse)) {
					return true;
				}
			}

		}
		return false;
	}

}
